import math
import random
import cPickle as pickle
from neat import config, population, chromosome, genome, visualize
from neat.nn import nn_pure as nn
#from neat.nn import nn_cpp as nn # C++ extension

from domination import core, run
import shutil
from tempfile import mkstemp
from shutil import move
from os import remove, close

import numpy as np

numGames = 2 # Number of games per evaluation of a genotype


#----------------------------------
# Get the files of all agents in the ladder
def replace(file, pattern, subst):
    #Create temp file
    fh, abs_path = mkstemp()
    new_file = open(abs_path,'w')
    old_file = open(file)
    for line in old_file:
        new_file.write(line.replace(pattern, subst))
    #close temp file
    new_file.close()
    close(fh)
    old_file.close()
    #Remove original file
    remove(file)
    #Move new file
    move(abs_path, file)

agent = "AgentBase"

# Copy main file
mainFile = "domination/main.py"
mainFileCopy = "domination/mainDONOTEDIT1_" + agent + ".py"
shutil.copyfile(mainFile, mainFileCopy)

# Open files and edit to use the right class
replace(mainFileCopy, "__AUTOREPLACEME__", agent)

ladder = ["domination/crippledAgent.py",
          "domination/agent.py",
          "domination/cereal_killers_v3_68.py",
          "domination/cereal_killers_v2_78.py"
          #"domination/warmainv12_82.py",
          #"domination/cynov4_85.py",
          #"domination/warmain_v4_87.py",
          #"domination/empire_v7_87.py",
          #"domination/trooperv8_89.py",
          #"domination/warmainv9_91.py",
          #"domination/trooperv6_92.py",
          #"domination/warmain_v7_92.py",
          #"domination/cereal_killers_v6_92.py",
          #"domination/trooperv7_100.py"
]
#---------------------------
#eschew_obfuscationv11_71.py
#"domination/empire_v15_94.py",#errors
#"domination/empire_v14_82.py",#errors
config.load('NEAT_config') # Contains all settings for the experiment
settings = core.Settings(max_steps=200, think_time=0.1) # Settings for the game

# set node gene type
chromosome.node_gene_type = genome.NodeGene

scoreMatrix = None
def eval_fitness(population):
    scoreMatrix = np.zeros((len(population), len(ladder)))
    chromoIndex = 0
    for chromo in population:
        # Create the neural network from the chromosome
        net = nn.create_ffphenotype(chromo)
        red_init = {'blob': net}
        
        # Play a number of games, and calculate fitness
        opponentIndex = 0
        for opponent in ladder: #
            print "now playing against " + opponent
            game = core.Game(mainFileCopy, opponent, red_init=red_init, blue_init={}, record=False, rendered=False, settings=settings)
            game.run()
            scoreMatrix[chromoIndex][opponentIndex] = float(game.score_red) / 1000
            opponentIndex += 1

        chromoIndex += 1

    print "Score Matrix (chromosomes x parasites):"
    print scoreMatrix
    
    opponentSums = np.sum(scoreMatrix, 0)
    opponentWeights = 1 / (opponentSums+1)
    print "Opponent weights:"
    print opponentWeights

    for i in range(len(population)):
        population[i].fitness = np.dot(scoreMatrix[i], opponentWeights)
        print "fitness of chromosome " + str(i) + ": " + str(population[i].fitness)

population.Population.evaluate = eval_fitness
pop = population.Population()

# Save every generation

for i in range(1000):
    if not i==0: pop = population.Population("checkpoint_" + str(i-1)) # Use this to restart from checkpoint
    pop.epoch(1, report=False, save_best=False, checkpoint_interval = 100000, checkpoint_generation = 1)
    visualize.plot_stats(pop.stats)  

#winner = pop.stats[0][-1]
#print 'Number of evaluations: %d' %winner.id



# Plots the evolution of the best/average fitness (requires Biggles)
visualize.plot_stats(pop.stats)
# Visualizes speciation
#visualize.plot_species(pop.species_log)

# Let's check if it's really solved the problem
#print '\nBest network output:'
#brain = nn.create_ffphenotype(winner)
#for i, inputs in enumerate(INPUTS):
#    output = brain.sactivate(inputs) # serial activation
#    print "%1.5f \t %1.5f" %(OUTPUTS[i], output[0])

# saves the winner
#file = open('winner_chromosome', 'w')
#pickle.dump(winner, file)
#file.close()




